#include <iostream>
#include <string>

using namespace std;

// 水果抽象类
class Fruit
{
public:
	virtual void GetFruit() = 0;
};

class Apple : public Fruit
{
public:
	void GetFruit()
	{
		cout << "苹果产地......."  << endl; 
	}
};

class Pear : public Fruit
{
public:
	void GetFruit()
	{
		cout << "梨子产地......."  << endl; 
	}
};

class Banana : public Fruit
{
public:
	void GetFruit()
	{
		cout << "香蕉产地......."  << endl; 
	}
};

class Plum : public Fruit
{
public:
	void GetFruit()
	{
		cout << "李子产地......" << endl;
	}

};

class AbsFactory
{
public:
	virtual Fruit* CreateProduct() = 0;
};

// 苹果工厂
class AppleFactory :public AbsFactory
{
public:
	Fruit* CreateProduct()
	{
		return new Apple;
	}
};

// 梨子工厂
class PearFactory :public AbsFactory
{
public:
	Fruit* CreateProduct()
	{
		return new Pear;
	}
};

// 香蕉工厂
class BananaFactory :public AbsFactory
{
public:
	Fruit* CreateProduct()
	{
		return new Banana;
	}
};

// 李子工厂
class PlumFactory : public AbsFactory
{
public:
	Fruit * CreateProduct()
	{
		return new Plum;
	}
};

template <typename T>
class DynCreatObj
{
public:
    template <typename Obj>
    void registerType(string type)  // 注册类型并保存对应的创建函数
    {
        function<T *()> func = [](){return new Obj();};

        if(m.find(type) == m.end())
        {
            m.emplace(type,func);
        }
        else
        {
            throw(string("类型已存在"));
        }
    }
    
    T * getObj(string type)
    {
        function<T* ()> func;

        if(m.find(type) != m.end())
        {
            func = m[type];

            return func();
        }
        else
        {
             throw(string("类型不存在"));
        }
        
    }

private:
    map<string,function<T *()>> m;  // 存储类型及其创建函数的映射
};



int main()
{
	 string  str;
	 
	 DynCreatObj<AbsFactory> dny_obj;
	 
	 dny_obj.registerType<AppleFactory>("apple");
	 dny_obj.registerType<BananaFactory>("banana");
	 
	 cin >> str;
	 
	 AbsFactory *factory = dny_obj.getObj(str);
	 
	 Fruit *f = factory->CreateProduct();
	 
	 f->GetFruit();
	 
	return 0;
}
